/***********************************************************************************
 * 文件名： mcu_adc.h
 * 作者： 刘言
 * 版本： 1
 * 说明：
 * 		ADC驱动。
 * 修改记录：
 * 	2024/9/7: 初版。 刘言。
***********************************************************************************/
#ifndef _MCU_ADC_H_
#define _MCU_ADC_H_

#include "mcu.h"

typedef struct _adc_cr_bits
{
    __IO uint32_t ADEN                     : 1;
    __IO uint32_t ADDIS                    : 1;
    __IO uint32_t ADSTART                  : 1;
    __IO uint32_t RSV0                     : 1;
    __IO uint32_t ADSTP                    : 1;
    __IO uint32_t VREF_BUFF_EN             : 1;
    __IO uint32_t VREF_BUFF_SEL            : 2;
    __IO uint32_t RSV1                     : 23;
    __IO uint32_t ADCAL                    : 1;
} adc_cr_bits_t;

typedef struct _adc_isr_bits
{
    __IO uint32_t RSV0                     : 1;
    __IO uint32_t EOSMP                    : 1;
    __IO uint32_t EOC                      : 1;
    __IO uint32_t EOSEQ                    : 1;
    __IO uint32_t OVR                      : 1;
    __IO uint32_t RSV1                     : 2;
    __IO uint32_t AWD                      : 1;
    __IO uint32_t RSV2                     : 24;
} adc_isr_bits_t;



#define _ADC_CH_V12        9      // 内部1.2V电压通道

// 用来通知转换结果的回调函数类型
typedef void (*adc_result_callback_t)(u16 result);


//APIs

#define ADC_FULL_VALUE  4095
#define ADC_CH_VREF     _ADC_CH_V12
#define ADCH_VREF   ADC_CH_VREF
#define ADC_VOL_VREF    1200

/**
 * ADC初始化，按照配置文件配置参数，确保ADC是失能状态调用才有效。
 * 已配置NVIC。时钟通过调用 Mcu_Init 统一开启,IO口分配与配置不在这里初始化（使用Gpio_Init）。
 */
void Adc_Init();


/**
 * [异步]开始一次扫描转换，将依次转换所有开启的通道(从0到9)，每个通道每次完成后会回调函数进行通知。
 * 注意：需要先把对应通道的IO口设置为模拟模式。
 * 将等待其它异步转换任务执行完毕。
 * 确保ADC已经使能。
 * 采样内部VREF通道至少需要10us。
 * 回调函数在中断中执行。
 */
void Adc_StartScan(adc_result_callback_t cb);

#define Adc_IsBusy() ((adc_cr_bits_t *)&ADC1->CR)->ADSTART

#define Adc_ClearAllFlag()     ADC1->ISR = 0XFF

#define Adc_GetResult()     ADC1->DR

/**
 * 设置通道选择值（选择接下来期望扫描转换的通道）。如果ADC已经使能,将会短暂失能ADC。
 * @param ch_sel 每个位为1代表开启对应通道，CH8是内部温度传感器，CH9是内部1.2V基准电压.
 */
void Adc_SetScanChSel(u32 ch_sel);

/**
 * 关闭ADC(ADC失能)，同时关闭了VREF、温度传感器
 * 注意，ADC关闭状态下开始转换可能会把程序锁死
 */
void Adc_Disable();

/**
 * 开启ADC,同时开启了VREF，温度传感器
 */
void Adc_Enable();


/**
 * 只需要在中断函数中调用此函数
 */
void Adc_EvIrqHander();

#endif


